#pragma once

#include "Socket.hpp"
#include "IOService.hpp"

using namespace socket_ns;

class ListenSock
{
private:
    uint16_t _port;
    unique_ptr<Socket> _listensock;

    IOService _ioservice;
public:
    ListenSock(IOService ioservice, uint16_t port = 8080)
        :_port(port)
        ,_listensock(make_unique<TcpSocket>())
        ,_ioservice(ioservice)
    {
        Analyze addr("0", _port);
        _listensock->BuildTcpServerSocket(addr);
    }

    void Accepter(Connection* conn)
    {
        //获取监听到的fd
        while(true)
        {
            Analyze addr;
            int code = 0;
            sleep(1);
            int fd = _listensock->Accept(addr, &code); //???
            // printf("[%s:%d] socket fd: %d\n", __FILE__, __LINE__, fd);

            if(fd >= 0)
            {
                conn->_react->AddConnection(fd,
                                            EPOLLIN | EPOLLET,
                                            bind(&IOService::IORecver, &_ioservice, placeholders::_1),
                                            bind(&IOService::IOSender, &_ioservice, placeholders::_1),
                                            bind(&IOService::IOExecter, &_ioservice, placeholders::_1)
                );
            }
            else
            {
                if(code == EWOULDBLOCK || code == EAGAIN)
                {
                    Log(Debug, "source accept finish");
                    break;
                }
                else if(code == EINTR)
                {
                    Log(Debug, "signal interrupt accept");
                    continue;
                }
                else
                {
                    Log(Warning, "accept error");
                    break;
                }
            }
        }
    }

    int getfd()
    {
        return _listensock->getfd();
    }

    ~ListenSock()
    {}

};